package org.abettor.util.crypto;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * DES、3DES 及 Blowfish 加密算法
 * @author <a href="http://www.abettor.org/" target="_blank">abettor</a>
 * @deprecated
 */
public class TripleDES
{
	/**
	 * 用于 DES 算法
	 * @see org.abettor.util.crypto.TripleDES#encrypt(byte[], String, byte[])
	 */
	public static final String ALGORITHM_DES		= "DES";
	/**
	 * 用于 3-DES 算法
	 * @see org.abettor.util.crypto.TripleDES#encrypt(byte[], String, byte[])
	 */
	public static final String ALGORITHM_3DES		= "DESede";
	/**
	 * 用于 Blowfish 算法
	 * @see org.abettor.util.crypto.TripleDES#encrypt(byte[], String, byte[])
	 */
	public static final String ALGORITHM_BLOWFISH	= "Blowfish";

	/**
	 * 普通16进制字符串
	 * @see org.abettor.util.crypto.TripleDES#bytesToHexString(byte[], int)
	 */
	public static final int HEX_STYLE_NORMAL	= 0;
	/**
	 * 16进制数据表示法（每一个 byte 间有空格隔开）
	 * @see org.abettor.util.crypto.TripleDES#bytesToHexString(byte[], int)
	 */
	public static final int HEX_STYLE_DATA		= 1;
	/**
	 * C 语言风格字符数组（每一个 byte 间有逗号隔开）
	 * @see org.abettor.util.crypto.TripleDES#bytesToHexString(byte[], int)
	 */
	public static final int HEX_STYLE_NUMBER	= 2;
	/**
	 * C 语言风格16进制字符串
	 * @see org.abettor.util.crypto.TripleDES#bytesToHexString(byte[], int)
	 */
	public static final int HEX_STYLE_C			= 3;

	//	私有构造函数，防止类被实例化
	private TripleDES()
	{
	}

	/**
	 * 生成一定长度的加密或解密密钥
	 * @param keyLen 所需要的密钥长度
	 * @return 返回 keyLen 长度的 byte 流密钥
	 */
	public static byte[] generateRandomKey(int keyLen)
	{
		byte [] byteKey = new byte[keyLen];
		byte [] tmp = { 0x00 };
		Random random = new Random();
		random.setSeed(System.currentTimeMillis());

		for(int i = 0; i < keyLen; i ++)
		{
			random.nextBytes(tmp);
			byteKey[i] = tmp[0];
		}

		return byteKey;
	}

	/**
	 * DES、3DES 或 Blowfish 加密算法
	 * @param bufferToEncrypt 待加密的 byte 流
	 * @param algorithm 加密算法名
	 * @param key 加密密钥
	 * @return 加密后的 byte 流，即密文。
	 */
	public static byte[] encrypt(byte[] bufferToEncrypt, String algorithm, byte[] key)
	{
		SecretKey desKey = new SecretKeySpec(key, algorithm);
		Cipher cipher = null;
		try
		{
			cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, desKey);

			return cipher.doFinal(bufferToEncrypt);
		}
		catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (NoSuchPaddingException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (InvalidKeyException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (IllegalBlockSizeException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (BadPaddingException e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * DES、3DES 或 Blowfish 解密算法
	 * @param bufferToDecrypt 待解密的 byte 流
	 * @param algorithm 解密算法名
	 * @param key 解密密钥
	 * @return 解密后的 byte 流，即原文。
	 */
	public static byte[] decrypt(byte[] bufferToDecrypt, String algorithm, byte[] key)
	{
		SecretKey desKey = new SecretKeySpec(key, algorithm);
		Cipher cipher = null;
		try
		{
			cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.DECRYPT_MODE, desKey);
			
			return cipher.doFinal(bufferToDecrypt);
		}
		catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (NoSuchPaddingException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (InvalidKeyException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (IllegalBlockSizeException e)
		{
			e.printStackTrace();
			return null;
		}
		catch (BadPaddingException e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 将 byte 流转化成一定格式的字符串
	 * @param byteBuf 待转化的 byte 流
	 * @param nHexStyle 生成的字符串格式
	 * @return 按照 nHexStyle 指定格式的字符串
	 */
	public static String bytesToHexString(byte[] byteBuf, int nHexStyle)
	{
		StringBuffer stringBuf = new StringBuffer();
		String tmp;
		int len = byteBuf.length;
		
		for(int n = 0; n < len; n ++)
		{
			tmp = Integer.toHexString(byteBuf[n] & 0xFF);
			if(tmp.length() == 1)
			{
				tmp = "0" + tmp;
			}

			stringBuf.append(tmp);
			stringBuf = new StringBuffer(stringBuf.toString().toUpperCase());
		}

		if(nHexStyle == HEX_STYLE_NORMAL)
		{
			return stringBuf.toString();
		}
		else if(nHexStyle == HEX_STYLE_DATA)
		{
			int lenOfString = stringBuf.length();
			for(int n = lenOfString - 2; n >= 2; n -= 2)
			{
				stringBuf.insert(n, " ");
			}
			
			return stringBuf.toString();
		}
		else if(nHexStyle == HEX_STYLE_C)
		{
			int lenOfString = stringBuf.length();
			for(int n = lenOfString - 2; n >= 0; n -= 2)
			{
				stringBuf.insert(n, "\\x");
			}

			return stringBuf.toString();
		}
		else if(nHexStyle == HEX_STYLE_NUMBER)
		{
			int lenOfString = stringBuf.length();
			for(int n = lenOfString - 2; n >= 2; n -= 2)
			{
				stringBuf.insert(n, ", 0x");
			}

			stringBuf.insert(0, "0x");
			
			return stringBuf.toString();
		}

		return null;
	}

	/**
	 * 将 byte 流转化成字符串
	 * @param byteBuf 待转化的 byte 流
	 * @return 将 byte 流转化后生成的字符串
	 */
	public static String bytesToHexString(byte[] byteBuf)
	{
		return bytesToHexString(byteBuf, HEX_STYLE_NORMAL);
	}
}
